#include <pty.h>
#include <utmp.h>

#include <stdio.h>
#include <stdlib.h>

#include <unistd.h>
#include <pthread.h>

/*
 * gcc -l pthread -l util -o ptymagic ptymagic.c
 * echo "PASSWORD" | ./ptymagic su -c "cat /etc/shadow"
 */

int readtunnel(int pty) {
    char ch;
    
    while (read(pty, &ch, 1) != -1) {
        write(1, &ch, 1);
    }
}

int writetunnel(int pty) {
    char ch;
    
    while (read(0, &ch, 1)) {
        write(pty, &ch, 1);
    }
}

int main(int argc, char **argv) {
    int pty;
    int child;
    int ret;
    
    pthread_t pread;
    pthread_t pwrite;
    
    if (argc < 2) {
        exit(EXIT_FAILURE);
    }
    
    child = forkpty(&pty, NULL, NULL, NULL);
    if (!child) {
        struct termios tios;
        
        tcgetattr(0, &tios);
        
        tios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
        tios.c_oflag &= ~(ONLCR);
        
        tcsetattr(0, TCSANOW, &tios);
        
        execv(argv[1], &argv[1]);
        
        exit(EXIT_FAILURE);
    }
    
    if (child == -1) {
        exit(EXIT_FAILURE);
    }
    
    read(pty, &ret, 1);
    write(1, &ret, 1);
    
    pthread_create(&pread, 0, readtunnel, pty);
    pthread_create(&pwrite, 0, writetunnel, pty);
    
    pthread_join(pread, 0);
    
    wait(&ret);
    
    if ((ret >= 0) && (ret <= 255)) {
        exit(ret);
    }
    
    exit(EXIT_FAILURE);
}